#!/usr/bin/env python
# -*- encoding: utf-8 -*-
import json
import os
import time
import webbrowser

from loguru import logger
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait

from . import utils, video


def make_browser():
    """
    新建浏览器驱动
    :return:
    """
    try:
        if not os.path.exists("user.json"):
            utils.popup("账号文件缺失问题", "请先配置user.json文件", "error")
            return None

        with open("user.json", mode="r", encoding="utf8") as fp:
            user_data = json.load(fp)
            utils.tmp_dict["user_data"] = user_data

        gecko_driver_path = os.path.join(os.getcwd(), "runtime", "geckodriver.exe")
        # logger.info(gecko_driver_path)
        firefox_binary_path = user_data.get("firefox_path", r"D:\Program Files\Mozilla Firefox\firefox.exe")  # 从配置文件读取 Firefox 路径

        firefox_service = Service(executable_path=gecko_driver_path)
        firefox_options = Options()

        if firefox_binary_path and os.path.exists(firefox_binary_path):
            firefox_options.binary_location = firefox_binary_path

        # 如果不是调试模式，就隐藏浏览器界面
        if not user_data.get("debug", True):
            firefox_options.add_argument("-headless")

        # driver = webdriver.Firefox()
        driver = webdriver.Firefox(options=firefox_options, service=firefox_service)
        # logger.info(driver)
        return driver
    except Exception as e:
        logger.error(e)
        utils.popup(
            "系统通知",
            f"启动Firefox浏览器失败\r\n可能是没有安装这个浏览器\r\n点击后自动打开浏览器下载该浏览器\r\n下载后请安装浏览器\r\n软件安装完毕后重新启动本软件",
            "error"
        )
        webbrowser.open("https://download.mozilla.org/?product=firefox-esr-latest-ssl&os=win64&lang=zh-CN")


def get_login_user_url(browser):
    """
    自动登陆并获取目录页面
    :param browser:
    :return: 登陆后的可成目录URL
    """
    try:
        user_id = utils.tmp_dict.get("user_data", {}).get("id", "")
        user_pass = utils.tmp_dict.get("user_data", {}).get("pwd", "")
        logger.info(f"已开始工号：{user_id} 学习任务")

        list_url = "https://avaryholding.yunxuetang.cn/kng/#/list?type=2"
        browser.get(list_url)
        # utils.popup("系统提示", "请先登录", "info")

        # 等待页面元素加载
        wait = WebDriverWait(browser, 10)

        # 检查系统语言，如果不是简体中文则切换
        lang__name = WebDriverWait(browser, 10).until(
            EC.presence_of_element_located((By.CLASS_NAME, "yxtbiz-nav-lang__name"))
        )
        if lang__name is not None:
            if lang__name.text != "简体中文":
                utils.switch_chinese(browser, "简体中文")
                logger.debug("已切换到简体中文")

        # 定位用户名输入框并输入用户名
        username_input = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='username'][type='text']")))
        username_input.send_keys(user_id)
        logger.info("已输入用户名")
        # 定位密码输入框并输入密码
        password_input = wait.until(
            EC.presence_of_element_located((By.CSS_SELECTOR, "input[name='username'][type='password']")))
        password_input.send_keys(user_pass)
        logger.info("已输入密码")

        try:
            # 方法1：直接定位到checkbox元素
            confirm_checkbox = wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, ".secret-protocol input[type='checkbox']"))
            )
            browser.execute_script("arguments[0].click();", confirm_checkbox)
            logger.info("已点击协议确认复选框")
        except TimeoutException:
            # 方法2：如果直接定位失败，尝试点击label元素
            try:
                confirm_label = wait.until(
                    EC.element_to_be_clickable((By.CSS_SELECTOR, ".secret-protocol label"))
                )
                confirm_label.click()
                logger.info("通过点击label元素确认协议")
            except TimeoutException:
                logger.warning("无法找到或点击协议确认元素，可能已默认选中")

        # 定位登录按钮并点击
        login_button = wait.until(EC.element_to_be_clickable((By.XPATH,
                                                              "//button[@class='yxtf-button mb16 yxtf-button--primary yxtf-button--huge']")))
        login_button.click()
        logger.info("已开始登陆")
        time.sleep(5)

        browser.refresh()
        return browser.current_url
    except Exception as e:
        logger.error(e)


def foreach_page_course(browser, new_list_url: str):
    """
    遍历当前页所有课件，不一定会全部打开，部分会跳过
    :param browser:
    :param new_list_url:
    :return:
    """
    for k in range(1, 17):
        list_task_title = None
        try:
            css_selector = f"ul.kng-list-new li:nth-child({k})"

            task = WebDriverWait(browser, 10).until(
                EC.presence_of_element_located((By.CSS_SELECTOR, css_selector))
            )

            # logger.debug(task)
            list_task_obj = task.text.strip().split("\n")
            try:
                # 获取课程标题
                title_element = task.find_element(By.CSS_SELECTOR, ".yxtf-tooltip")
                list_task_title = title_element.text.strip()

                # 获取课程状态标签
                tag_elements = task.find_elements(By.CSS_SELECTOR, ".kng-list-new__tag")
                list_task_status = " ".join([tag.text.strip() for tag in tag_elements])

            except Exception:
                # 这里有可能是跟着变化
                if len(list_task_obj) == 5:
                    list_task_title = list_task_obj[2]
                    list_task_status = list_task_obj[1]
                else:
                    list_task_title = list_task_obj[1]
                    list_task_status = list_task_obj[0]

            if "课程" in list_task_status:
                continue

            if "已学完" in list_task_status.strip():
                continue

            if list_task_title in utils.bad_list:
                continue

            skip_list = utils.load_skip_list()
            if list_task_title in skip_list:
                logger.info(f"课程 '{list_task_title}' 在跳过列表中，直接跳过")
                continue

            logger.info(f"课程信息:{list_task_obj}，准备进入课程，{list_task_title}")
            time.sleep(1)

            utils.click_element(task, f"点击课程，{list_task_title}", 3)
            time.sleep(2)

            # 切换2倍加速
            new_current_url = f"{browser.current_url}&rate=2"
            utils.navigate_and_wait(browser, new_current_url, "尝试切换2倍速模式", 2)
            logger.info("进入课程内部页面")
            browser.refresh()
            time.sleep(2)

            if browser.current_url[-6:] != "rate=2":
                logger.warning("切换2倍速失败,使用常规速度学习")

            # 没学习的开始学习，点击开始播放按钮，这个是中间的大的紫色按钮
            start_btn = browser.find_element(By.CLASS_NAME, 'yxtulcdsdk-course-player__back').find_element(
                By.CLASS_NAME, 'yxtulcdsdk-flex-center').find_element(By.CLASS_NAME,
                                                                      "yxtulcdsdk-flex-center").find_element(
                By.TAG_NAME, "button")

            logger.info("找到了开始按钮按钮")
            if start_btn is not None:
                # 按钮存在，点击它
                utils.click_element(start_btn, "点击开始学习，开始播放", 3)
                # start_btn.click()
                time.sleep(2)

            # 在这里区分多种类型的课程
            task_url = browser.current_url

            if "video/play" in task_url:
                video.process_video(browser, start_btn, list_task_title)
            else:
                logger.error("未知的课程类型，跳过")
                continue

        except Exception as e:
            logger.error(e)
            if list_task_title is not None:
                logger.error(f"学习状态确认失败，{list_task_title}，加入跳过清单")
                utils.bad_list.append(list_task_title)

        # 学习完成，开始返回
        utils.navigate_and_wait(browser, new_list_url, "返回任务列表", 2)


def foreach_all_pages(browser, new_list_url: str):
    """
    遍历翻页，循环任务列表,检查是否有下一页，直到没有下一页
    :param browser:
    :param new_list_url:
    :return:
    """
    while True:
        try:
            # 没有下一页说明已经到最后一页了，直接退出循环
            if utils.find_exsit_element(browser, "button[disabled][class='btn-next']") is not None:
                break

            # 如果没有找到最后一页，则继续循环
            try:
                active_page_element = WebDriverWait(browser, 10).until(
                    EC.presence_of_element_located((By.CSS_SELECTOR, "ul.yxtf-pager li.number.active"))
                )
                active_task_page_number = active_page_element.text
                logger.info(f"当前页数：{active_task_page_number}")
            except TimeoutException:
                # 如果在指定时间内没有找到元素，捕获异常并处理
                logger.warning("等待元素超时，未能找到激活的页码。")

            # 循环当前页课程
            logger.debug("开始循环当前页面课程")
            foreach_page_course(browser, new_list_url)
            logger.debug("结束循环当前页面课程")

            browser.find_element(By.TAG_NAME, "body").send_keys(Keys.END)
            logger.debug("已滚动到底部")
            nav_pages = utils.find_exsit_element(browser, "button.btn-next")
            logger.debug(nav_pages)
            if nav_pages:
                utils.click_element(nav_pages, "点击下一页", 3)
                new_list_url = browser.current_url

        except Exception as e:
            logger.error(e)
            continue


def main():
    """
    运行
    """
    try:
        # os.system("cls")
        logger.add(
            "log/{time:YYYYMMDD}.log",
            level="INFO",
            rotation="10 MB",
            encoding="utf-8",
            enqueue=True,
        )
        browser = make_browser()
        if browser is None:
            logger.error("浏览器初始化失败")
            return

        browser.maximize_window()
        list_url = get_login_user_url(browser)
        if not list_url:
            logger.error("获取课程列表失败")
            return

        utils.navigate_and_wait(browser, list_url, "登陆成功，重新进入课程列表页面", 2)

        next_btn = utils.find_exsit_element(browser, ".driver-next-btn")
        if next_btn is not None:
            utils.click_element(next_btn, "点击引导按钮", 2)

        logger.debug("完成引导流程，下面开始学习")
        foreach_all_pages(browser, list_url)

    except Exception as e:
        logger.error(e)
    finally:
        browser.quit()  # noqa
